class unionset
{
public:
    vector<int> fa;
    unionset(int n)
    {
        for (int i = 0; i < n; i++) fa.push_back(i);
    }
    int find(int a)
    {
        return fa[a] == a ? a : fa[a] = find(fa[a]);
    }
    void merge(int a, int b)
    {
        fa[find(a)] = find(b);
    }
    int num()
    {
        int ans = 0;
        for (int i = 0; i < fa.size(); i++)
        {
            if (fa[i] == i) ans += 1;
        }
        return ans;
    }
};




class Solution {
public:
    int removeStones(vector<vector<int>>& stones) {
        unordered_map<int, int> h, l;
        unionset s(stones.size());
        for (int i = 0; i < stones.size(); i++)
        {
            if (h.find(stones[i][0]) == h.end() && l.find(stones[i][1]) == l.end())
            {
                h[stones[i][0]] = l[stones[i][1]] = i;
            }
            else
            {
                int temp1 = stones[i][0], temp2 = stones[i][1];
                if (h.find(temp1) != h.end() && l.find(temp2) != l.end())
                {
                    s.merge(h[temp1], i);
                    s.merge(l[temp2], i);
                }
                else if (h.find(temp1) != h.end())
                {
                    s.merge(h[temp1], i);
                    l[temp2] = i;
                }
                else
                {
                    s.merge(l[temp2], i);
                    h[temp1] = i;
                }
            }
        }
        return stones.size() - s.num();
    }
};